package org.gpp.proj1.logic.core.server;

import java.util.Map;
import java.util.concurrent.BlockingQueue;

import org.gpp.proj1.communication.manager.NetworkManager;
import org.gpp.proj1.communication.protocol.Message;
import org.gpp.proj1.communication.protocol.ProtocolIdentifiers;
import org.gpp.proj1.communication.protocol.ProtocolMessageParser;
import org.gpp.proj1.communication.protocol.ProtocolParameters;
import org.gpp.proj1.logic.metadata.RobotPartCategory;

import com.jme.util.LoggingSystem;

/**
 * Thread that handles the server requests
 * 
 * @author Paolo Victor, paolovictor@gmail.com
 */
public class ServerRequestHandler implements Runnable {

	private BlockingQueue<Message> messages;

	private boolean stopRunning = false;

	private final NetworkManager networkManager;

	private final Server server;

	/**
	 * Creates a new RequestHandler instance
	 * @param messages The queue the handler will take messages from
	 */
	public ServerRequestHandler( Server server, NetworkManager networkManager, BlockingQueue<Message> messages ) {
		this.server = server;
		this.networkManager = networkManager;
		this.messages = messages;
	}

	/**
	 * Stops this thread
	 */
	public void stopRunning() {
		this.stopRunning = true;			
	}

	public void run() {

		while( ! stopRunning  ) {
			try {
				Message message = messages.take();

				// Chat messages are accepted during all phases
				if( message.getIdentifier().equals( ProtocolIdentifiers.CHAT ) ) {
					LoggingSystem.getLogger().info( "Chat: " + message );

					// Broadcasting message to clients
					networkManager.broadcastMessage( message );

					//////////////////////////////////////////////////
					// Lobby phase
					//////////////////////////////////////////////////
				} else if( server.getCurrentPhase().equals( ServerPhases.LOBBY ) ) {

					if( message.getIdentifier().equals( ProtocolIdentifiers.HELLO ) ) {
						LoggingSystem.getLogger().info( "Client hello: " + message.getSenderId() );

						// Adding client to connected clients list
						server.addOnlineClient( message.getSenderId(), message.getParameters()[ ProtocolParameters.HELLO_MESSAGE_ALIAS ] );
					} else if( message.getIdentifier().equals( ProtocolIdentifiers.TOGGLEREADINESS ) ) {

						server.toggleReadiness( message.getSenderId() );
					}
					//////////////////////////////////////////////////
					// Initialization phase
					//////////////////////////////////////////////////
				} else if( server.getCurrentPhase().equals( ServerPhases.INIT ) ) {

					if( message.getIdentifier().equals( ProtocolIdentifiers.MYROBOTDATA ) ) {

						String[] rawRobotDataEntry = ProtocolMessageParser.parseMyRobotData( message );
						Map<String, Map<RobotPartCategory, String>> robotMappingEntry = ProtocolMessageParser.parseRobotData( message );
						
						server.playerHasSentRobotData( message.getSenderId(), rawRobotDataEntry, robotMappingEntry );
					} else if( message.getIdentifier().equals( ProtocolIdentifiers.TOGGLEREADINESS ) ) {
						
						server.toggleReadiness( message.getSenderId() );
						
						if( server.mayStartGame() ) {
							this.server.startGame();
						}
					}
				} else if( server.getCurrentPhase().equals( ServerPhases.INGAME ) ) {
					
					if( message.getIdentifier().equals( ProtocolIdentifiers.WHOSETURNISIT ) ) {
						
						server.sendNextTurn( message.getSenderId() );
					} else if( message.getIdentifier().equals( ProtocolIdentifiers.ENDTURN ) ) {
						
						server.playerEndedTurn();
					} else if( message.getIdentifier().equals( ProtocolIdentifiers.MOVEROBOT ) ) {
						
						String robot = message.getParameters()[0];
						int x = Integer.parseInt( message.getParameters()[1] );
						int y = Integer.parseInt( message.getParameters()[2] );
						server.playerMovedRobot( message.getSenderId(), robot, x, y );
					} else if( message.getIdentifier().equals( ProtocolIdentifiers.ATTACK ) ) {
						
						String robot = message.getParameters()[0];
						int xTarget = Integer.parseInt( message.getParameters()[1] );
						int yTarget = Integer.parseInt( message.getParameters()[2] );
						String part = message.getParameters()[3];
						String attack = message.getParameters()[4];
						
						server.playerAttacked( message.getSenderId(), robot, xTarget, yTarget, part, attack );
						
					}
				}
			} catch (InterruptedException e) {
				LoggingSystem.getLogger().warning( "Failed to handle incoming request" );
			}
		}
	}
}
